package br.com.rapidrest.servlet;

import java.io.IOException;
import java.io.Serializable;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import br.com.rapidrest.chain.Chain;
import br.com.rapidrest.exception.ChainException;
import br.com.rapidrest.request.RequestHandler;

public class RapidRestFilter implements Filter, Serializable {

	private static final long serialVersionUID = -4278942130995632743L;

	public static final String HANDLER_CLASS_INIT_PARAM = "radidrest.handler";

	public static final String HANDLER_CONTEXT_PREFIX = "radidrest.handler";
	
	private String handlerAppContextKey;

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		if (request instanceof HttpServletRequest
				&& response instanceof HttpServletResponse) {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			HttpServletResponse httpResponse = (HttpServletResponse) response;
			
			ServletContext servletContext = httpRequest.getSession().getServletContext();
			RequestHandler handler = (RequestHandler) servletContext.getAttribute(handlerAppContextKey);
			
			Chain chain = handler.createChain(httpRequest, httpResponse, filterChain);
			try {
				chain.proceed();
			} catch (ChainException e) {
				// TODO ??
				throw new ServletException(e);
			}
		} else {
			filterChain.doFilter(request, response);
		}
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		String handlerClassName = filterConfig
				.getInitParameter(HANDLER_CLASS_INIT_PARAM);
		if (handlerClassName == null) {
			throw new ServletException("Parameter " + HANDLER_CLASS_INIT_PARAM
					+ " is required.");
		}
		try {
			RequestHandler handler = initHandler(handlerClassName);
			handlerAppContextKey = HANDLER_CONTEXT_PREFIX + "." + filterConfig.getFilterName();
			filterConfig.getServletContext().setAttribute(handlerAppContextKey, handler);
		} catch (ClassNotFoundException e) {
			throw new ServletException(e);
		} catch (InstantiationException e) {
			throw new ServletException(e);
		} catch (IllegalAccessException e) {
			throw new ServletException(e);
		}
	}

	@SuppressWarnings("unchecked")
	private RequestHandler initHandler(String className)
			throws ClassNotFoundException, InstantiationException,
			IllegalAccessException {
		Class<RequestHandler> handlerClass = (Class<RequestHandler>) Class
				.forName(className);
		return handlerClass.newInstance();
	}

	String getHandlerAppContextKey() {
		return handlerAppContextKey;
	}

	void setHandlerAppContextKey(String handlerAppContextKey) {
		this.handlerAppContextKey = handlerAppContextKey;
	}

}